package cn.tedu.lbs.basic.web.service;

import cn.tedu.lbs.basic.web.repository.TagLibRepository;
import cn.tedu.lbs.basic.web.repository.UserRepository;
import cn.tedu.lbs.basic.web.repository.UserTagsRepository;
import cn.tedu.lbs.basic.web.util.AuthenticationContextUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.pojo.basic.param.UserTagsParam;
import com.tarena.lbs.pojo.basic.po.TagLibraryPO;
import com.tarena.lbs.pojo.basic.po.UserPO;
import com.tarena.lbs.pojo.basic.po.UserTagsPO;
import com.tarena.lbs.pojo.basic.vo.TagLibraryVO;
import com.tarena.lbs.pojo.basic.vo.TagVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TagService {
    @Autowired
    private TagLibRepository tagLibRepository;
    @Autowired
    private UserTagsRepository userTagsRepository;
    @Autowired
    private UserRepository userRepository;
    /**
     *第一种方案 创建hashMap 从数据库 先查询以及标签的列表 pos where tag_type=0 and tag_parent_id=0
     *循环这个pos 每次拿到一个po对象(一级标签) 一级标签id 查询当前一级标签对应的二级标签 pos
     *where tag_parent_id=#{一级标签id}
     *缺点: 现在数据有2个一级标签 每个一级标签下有3个二级标签 需要查询连接数据库 3次
     *导致业务层为了封装对应数据结构 连接操作数据库的次数过多
     *第二种方案 一次性读取 标签表里所有的文章标签(8个pos)
     *在业务层解析这个集合 把一级标签筛选过滤出来 在筛选过滤二级标签
     */
    public Map<String, List<TagVO>> tagMaps(Integer tagType) {
        Map<String,List<TagVO>> tagMaps = new HashMap<>();
        //方案二: 一次查询 获取所有数据 业务中解析数据
        //1.从数据库查询所有文章标签
        QueryWrapper<TagLibraryPO> queryAll = new QueryWrapper<>();
        queryAll.eq("tag_type", tagType);
        List<TagLibraryPO> all = tagLibRepository.list(queryAll);
        //2.希望从all 解析筛选出来 所有一级标签 tagParentId=0 使用集合流 过滤方法
        List<TagLibraryPO> onePos = all.stream().filter(po -> {
            //在判断数字相等逻辑中 如果涉及到Integer Long封装类 有自动拆包 自动装包的 尽可能不使用== 换成equal
            return po.getTagParentId().equals(0);
        }).collect(Collectors.toList());
        for (TagLibraryPO one : onePos) {
            Integer oneId = one.getId();
            //3.从all再次筛选 筛出了当前标签下级标签po列表
            List<TagLibraryPO> twoPos = all.stream().filter(po -> {
                return po.getTagParentId().equals(oneId);
            }).collect(Collectors.toList());
            String key=one.getTagName();
            List<TagVO> vos= twoPos.stream().map(po->{
                TagVO vo=new TagVO();
                vo.setTagCategoryName(key);
                TagLibraryVO bo=new TagLibraryVO();
                BeanUtils.copyProperties(po,bo);
                vo.setTagLibraryBO(bo);
                return vo;
            }).collect(Collectors.toList());
            tagMaps.put(key,vos);
        }
        //方案一: 多次查询数据库 寻找不同数据
        //1.先利用tagType和tagParentId查询一级标签
        /*QueryWrapper<TagLibraryPO> queryOne = new QueryWrapper<>();
        queryOne.eq("tag_type", tagType);
        queryOne.eq("tag_parent_id", 0);
        List<TagLibraryPO> onePos = tagLibRepository.list(queryOne);
        //2.对一级标签做循环 每次获得一级标签id,查询二级标签
        for (TagLibraryPO one : onePos) {
            Integer oneId = one.getId();//是二级标签的parentId
            QueryWrapper<TagLibraryPO> queryTwo = new QueryWrapper<>();
            queryTwo.eq("tag_parent_id", oneId);
            List<TagLibraryPO> twoPos = tagLibRepository.list(queryTwo);
            //每次循环 都封装一个map key-value key是一级标签名字 value需要转化二级标签po
            String key=one.getTagName();
            List<TagVO> vos= twoPos.stream().map(po->{
                 TagVO vo=new TagVO();
                 vo.setTagCategoryName(key);
                 TagLibraryVO bo=new TagLibraryVO();
                 BeanUtils.copyProperties(po,bo);
                 vo.setTagLibraryBO(bo);
                 return vo;
            }).collect(Collectors.toList());
            tagMaps.put(key,vos);
        }*/
        return tagMaps;
    }

    public void userBindTags(UserTagsParam userTagsParam) throws BusinessException {
        //1.获取用户id
        Integer userId = getUserId();
        //2.根据id 删除lbs_user_tags中的数据
        removeUserTags(userId);
        //3.组织数据批量新增
        saveBatchUserTags(userTagsParam,userId);
        //4.更新用户状态
        updateUserStatus(userId,1);
    }

    private void updateUserStatus(Integer userId, Integer status) {
        //update lbs_user set status=? where id=?
        UserPO poParam=new UserPO();
        poParam.setId(userId);
        poParam.setStatus(status);
        userRepository.updateById(poParam);//传递一个po对象必须存在属性id 其他的属性都是set值
    }

    private void saveBatchUserTags(UserTagsParam userTagsParam, Integer userId) {
        //insert into lbs_user_tags (user_id,tag_id) value (5115,3),(5115,28),(5115,29)
        //1.根据入参 解析tagIds 封装多个UserTagsPO的元素集合 3,28,29
        String[] tagIds = userTagsParam.getTagIds().split(",");
        List<UserTagsPO> pos = Arrays.stream(tagIds).map(tagId -> {
            UserTagsPO po = new UserTagsPO();
            po.setTagId(Integer.parseInt(tagId));
            po.setUserId(userId);
            return po;
        }).collect(Collectors.toList());
        //2.调用仓储层 批量执行新增
        userTagsRepository.saveBatch(pos);
    }

    private void removeUserTags(Integer userId) {
        //delete from lbs_user_tags where user_id=?
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("user_id",userId);
        userTagsRepository.remove(queryWrapper);
    }

    private Integer getUserId() throws BusinessException {
        UserPrinciple userPrinciple = AuthenticationContextUtil.get();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证解析失败"));
        return userPrinciple.getId();
    }
}
